﻿namespace Reals.Parellel
{
  #region Using directives

  using System;
  using System.Collections.Generic;
  using System.Text;

  #endregion

  /// <summary>
  /// 微等时面.
  /// </summary>
  public interface MicroSynching:IDisposable
  {
    /// <summary>
    /// 获取等时面的名称。
    /// </summary>
    string Name { get;}
    /// <summary>
    /// 判断当前等时面上是否具有微过程。
    /// </summary>
    bool HasMicroProcesses { get;}
    /// <summary>
    /// 判别当前对象是否已经被处置。
    /// </summary>
    bool IsDisposed { get;}
    /// <summary>
    /// 获取等时面上的所有微过程。
    /// </summary>
    ICollection<MicroProcess> MicroProcesses { get;}
    /// <summary>
    /// 完成当前等时面中所有并行微过程.
    /// </summary>
    void Tick();
    /// <summary>
    /// 添加微过程。
    /// </summary>
    MicroProcess Add(MicroProcess process);
    /// <summary>
    /// 移除微过程。
    /// </summary>
    MicroProcess Remove(MicroProcess process);
    /// <summary>
    /// 清除所有和Target相关的微过程.
    /// </summary>
    object RemoveTarget(object target);
  }


  /// <summary>
  /// 微等时面的实现.
  /// </summary>
  public class MicroSynchingImpl : MicroSynching
  {
    #region Statics
    public static MicroSynchingImpl of(string name,params MicroProcess[] processes)
    {
      return new MicroSynchingImpl(name,processes);
    }
    #endregion
    #region Fields
    protected bool isDisposed = false;
    protected string name = string.Empty;
    protected LinkedList<MicroProcess>  microProcesses = null;
    #endregion
    #region Properties
    public virtual string Name
    {
      get
      {
        return this.name;
      }
    }
    public virtual bool HasMicroProcesses
    {
      get
      {
        return this.microProcesses != null && this.microProcesses.Count > 0;
      }
    }
    public virtual ICollection<MicroProcess> MicroProcesses
    {
      get
      {
        return this.microProcesses == null ?
          this.microProcesses = new LinkedList<MicroProcess>() :
          this.microProcesses;
      }
    }
    public virtual bool IsDisposed
    {
      get
      {
        return this.isDisposed;
      }
    }
    #endregion
    #region Constructors
    public MicroSynchingImpl(string name,params MicroProcess[] processes) : base() 
    {
      this.name = name == null ? string.Empty : name;

      if (processes != null)
      {
        foreach (MicroProcess process in processes)
        {
          if (process != null)
          {
            this.Add(process);
          }
        }
      }
    }
    #endregion
    ~MicroSynchingImpl()
    {
      this.Dispose();
    }
    #region Methods
    /// <summary>
    /// 并行完成当前
    /// 等时面上的
    /// 所有微过程.
    /// </summary>
    public virtual void Tick()
    {
      if (this.HasMicroProcesses)
      {
        LinkedListNode<MicroProcess> node = this.microProcesses.First;

        while (node != null)
        {
          LinkedListNode<MicroProcess> nextNode = node.Next;
          if (node != null && node.Value != null)
          {
            //If no need to lauch the process, remove it.
            if (node.Value() == false)
            {
              this.microProcesses.Remove(node);
            }
          }
          node = nextNode;
        }
      }
    }
    public virtual MicroProcess Add(MicroProcess process)
    {
      if (this.microProcesses == null || this.microProcesses.Find(process) == null)
      {
        this.MicroProcesses.Add(process);
      }
      return process;
    }
    public virtual MicroProcess Remove(MicroProcess process)
    {
      if (this.microProcesses !=null && this.microProcesses.Find(process) != null)
      {
        this.MicroProcesses.Remove(process);
      }
      return process;
    }
    public object RemoveTarget(object target)
    {
      if (target != null && this.HasMicroProcesses)
      {
        LinkedListNode<MicroProcess> node = this.microProcesses.First;
        while (node!=null)
        {
          if (node != null && node.Value != null && node.Value.Target == target)
          {
            this.microProcesses.Remove(node);
          }
          node = node.Next;
        }
      }
      return target;
    }

    public virtual void Dispose()
    {
      if (!this.isDisposed)
      {
        GC.SuppressFinalize(this);

        this.name = null;
        if (this.HasMicroProcesses)
        {
          this.MicroProcesses.Clear();
        }
        this.isDisposed = true;
      }
    }
    #endregion
  }
}
